package fr.jade.fraclite.orb;

import java.io.IOException;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import fr.jade.fraclite.api.ComponentInterface;
import fr.jade.fraclite.orb.api.Binder;
import fr.jade.fraclite.orb.api.Name;
import fr.jade.fraclite.orb.api.NamingException;

public class UnicastStubFactory implements StubFactory {
  
  ClassLoader cl = null;
  
  Skeleton s = null;
  ExecutorService es;
  
  public UnicastStubFactory(ClassLoader cl) {
    this.cl=cl;
    es = Executors.newCachedThreadPool();
  }

  public Object newStub(Binder binder, Name name) throws NamingException{
    UnicastStub stub = new UnicastStub(name);
    try {
      String signature = name.getSignature();
      Class<?> itf = cl.loadClass(signature);
      Class<?>[] itfs = new Class[]{itf, ComponentInterface.class};
      return Proxy.newProxyInstance(cl, itfs, stub);
    } catch (ClassNotFoundException e) {
      throw new NamingException("Cannot create stub "+e.toString() );
    }
  }
  
  public Object newSkeleton(Map<String,?> hints, Object target, Binder naming) throws NamingException{
    int port = 0;
    if (hints != null){
      port = Integer.parseInt((String)hints.get("port"));
    }
    if(s == null){
      try {
        s = new UnicastSkeleton(es, naming, port);
      } catch (IOException e) {
        throw new NamingException("Cannot create skeleton "+e.toString() );
      }
      es.execute(s);
    }
    s.registerTarget(target);
    return s;
  }
}
